﻿using Abp.Application.Services.Dto;
using Abp.Authorization.Users;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.Organizations;
using Abp.UI;
using Camc.Quality.Authorization.Users;
using Camc.Quality.Authorization.Users.Dto;
using Camc.Quality.Bop;
using Camc.Quality.Bop.TreeObject;
using Camc.Quality.Business;
using Camc.Quality.Common;
using Camc.Quality.IOperationHistory;
using Camc.Quality.ITech;
using Camc.Quality.OperationHistory;
using Camc.Quality.ProcessRoute;
using Camc.Quality.Quality;
using Camc.Quality.RecordTable.FormClass;
using Camc.Quality.StoreManagement.StoragePut;
using Camc.Quality.SystemManagement;
using Camc.Quality.TrepanningManager.BomAnalyse;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static Camc.Quality.StoreManagement.StoragePut.StoreStockContent;

namespace Camc.Quality.ProductionPlan
{
    public class ProductionDesignAppService : QualityAppServiceBase, IRoute
    {
        const string forenoonStart = "8:30:00";
        const string forenoonEnd = "11:30:00";
        const string afternoonStart = "13:30:00";
        const string afternoonEnd = "18:30:00";

        private readonly IRepository<BopNode, Guid> _bopNodeRepository;
        private readonly IRepository<BopDesc, Guid> _bopDescRepository;
        private readonly IRepository<TechniqueEntity, Guid> _techniqueEntityRepository;
        private readonly IRepository<ProcessesEntity, Guid> _processesEntityRepository;
        private readonly IRepository<WorkStepEntity, Guid> _workStepEntityRepository;
        private readonly IRepository<ProductionScheduler, Guid> _productionSchedulerRepository;
        private readonly IRepository<ProcessLine, Guid> _processLineRepository;
        private readonly IRepository<User, long> _userRepository;
        public readonly CodeFormatDescAppService _codeFormatDescAppServiceRepsitory;
        private readonly IRepository<OrganizationUnit, long> _organizationUnitRepository;
        private readonly IRepository<UserOrganizationUnit, long> _userOrganizationUnitRepository;
        private readonly IRepository<LoadPieceEntity, Guid> _loadPieceRepository;
        public readonly IRepository<StoreStockContent, Guid> _storeStockContentRepsitory;
        private readonly BomAnalyseAppService _bomAnalyseAppServiceRepository;
        private readonly IRepository<ModifyManage, Guid> _modifyManageRepository;
        private readonly IOperationHistoryAppService _iOperationHistoryAppService;

        public ProductionDesignAppService(IRepository<BopNode, Guid> bopNodeRepository,
            IRepository<BopDesc, Guid> bopDescRepository,
            IRepository<TechniqueEntity, Guid> techniqueEntityRepository,
            IRepository<ProcessesEntity, Guid> processesEntityRepository,
            IRepository<WorkStepEntity, Guid> workStepEntityRepository,
            IRepository<ProductionScheduler, Guid> productionSchedulerRepository,
            IRepository<ProcessLine, Guid> processLineRepository,
            IRepository<User, long> userRepository,
            IOperationHistoryAppService iOperationHistoryAppService,
            CodeFormatDescAppService codeFormatDescAppServiceRepsitory,
            IRepository<OrganizationUnit, long> organizationUnitRepository,
            IRepository<UserOrganizationUnit, long> userOrganizationUnitRepository,
            IRepository<LoadPieceEntity, Guid> loadPieceRepository,
            IRepository<StoreStockContent, Guid> storeStockContentRepsitory,
            BomAnalyseAppService bomAnalyseAppServiceRepository,
            IRepository<ModifyManage, Guid> modifyManageRepository
            )
        {
            _bopNodeRepository = bopNodeRepository;
            _bopDescRepository = bopDescRepository;
            _techniqueEntityRepository = techniqueEntityRepository;
            _processesEntityRepository = processesEntityRepository;
            _workStepEntityRepository = workStepEntityRepository;
            _productionSchedulerRepository = productionSchedulerRepository;
            _processLineRepository = processLineRepository;
            _userRepository = userRepository;
            _iOperationHistoryAppService = iOperationHistoryAppService;
            _codeFormatDescAppServiceRepsitory = codeFormatDescAppServiceRepsitory;
            _organizationUnitRepository = organizationUnitRepository;
            _userOrganizationUnitRepository = userOrganizationUnitRepository;
            _loadPieceRepository = loadPieceRepository;
            _storeStockContentRepsitory = storeStockContentRepsitory;
            _bomAnalyseAppServiceRepository = bomAnalyseAppServiceRepository;
            _modifyManageRepository = modifyManageRepository;
        }
        /// <summary>
        /// 根据型号和发次获取树结构
        /// </summary>
        /// <param name="model">型号</param>
        /// <param name="lotNo">发次</param>
        /// <returns></returns>
        public AssignmentTreeOutput GetProductionDesigenTree(Guid? model, Guid? lotNo)
         {
            AssignmentTreeOutput output = new AssignmentTreeOutput();
         
            var bopDescTemp = _bopDescRepository.GetAll().Where(d => d.ModelId == model && d.LotNoId == lotNo).FirstOrDefault();
            if (bopDescTemp != null)
            {
                output.Id = bopDescTemp.Id;
                output.ParentId = Guid.Empty;
                output.NodeDrawingNo = bopDescTemp.DrawingNo;
                output.NodeName = bopDescTemp.ModelName;
                output.IsRelation = 0;
                output.NodeLevel = 0;
                LoadChildNode(bopDescTemp.Id, output);
                return output;
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 加载bop节点递归
        /// </summary>
        /// <param name="Id"></param>
        /// <param name="treeNodeDto"></param>
        private void LoadChildNode(Guid Id, AssignmentTreeOutput treeNodeDto)
        {
            var bopNodeList = _bopNodeRepository.GetAll().Where(c => c.ParentId == Id).OrderBy(d=>d.CreationTime);
            //var list = ObjectMapper.Map<List<BopNodeDto>>(bopNodeList);
            foreach (var item in bopNodeList)
            {
                AssignmentTreeOutput tree = new AssignmentTreeOutput();
                tree.Id = item.Id;
                tree.ParentId = item.ParentId;
                tree.NodeDrawingNo = item.NodeDrawingNo;
                tree.NodeName = item.NodeName;
                if (item.TechniqueEntityId == null)
                    tree.IsRelation = 0;
                else
                {
                    tree.IsRelation = 1;
                    var tech = _techniqueEntityRepository.GetAll().FirstOrDefault(d=>d.Id==  item.TechniqueEntityId.Value);
                    if (tech != null)
                    {

                        tree.OutboundStatusDesc = GetEnumDesc(tech.OutboundState);
                    }
                    else
                    {
                        tree.OutboundStatusDesc = "";
                    }
                    
                }
                  
                tree.NodeLevel = item.NodeLevel;   //NodeLevel;
                tree.ParentCode = item.ParentCode;
                tree.NodeCode = item.NodeCode;
                tree.IsLeaf = item.IsLeaf;
                tree.IsExport = item.IsExport;
                //递归性质，函数内调用自身函数
                //NodeLevel++;
                LoadChildNode(item.Id, tree);
                //NodeLevel--;
                //递归结束的终点条件
                treeNodeDto.TreeList.Add(tree);
            }
        }
        /// <summary>
        /// 懒加载获取工序工步树节点
        /// </summary>
        /// <param name="NodeId"></param>
        /// <returns></returns>
        public List<AssignmentTreeOutput> GetProductionTechquine(Guid NodeId)
        {
            AssignmentTreeOutput output = new AssignmentTreeOutput();
            LoadTechquine(NodeId, output);
            return output.TreeList;
        }
        /// <summary>
        /// 加载工步工序节点
        /// </summary>
        /// <param name="NodeId"></param>
        /// <param name="treeNodeDto"></param>
        private void LoadTechquine(Guid NodeId, AssignmentTreeOutput treeNodeDto)
        {
            //获取节点信息的工艺规程编码
            var bomNode = _bopNodeRepository.FirstOrDefault(x => x.Id == NodeId);
            string processCode = bomNode.ProcessCode;
            //根据工艺规程编码获取工艺文件表Id,已关联文件
            var tech = _techniqueEntityRepository.FirstOrDefault(x => x.Id == bomNode.TechniqueEntityId);
            if (tech == null) return;
            Guid techId = tech.Id;
            //获取工序和工步的信息，并做相应的排序
            var processesList = _processesEntityRepository.GetAllIncluding(p => p.WorkStepEntities).Where(p => p.TechniqueEntityId == techId).OrderBy(n => n.ProcessesSequence).ToList();
            processesList.ToList().ForEach(q => q.WorkStepEntities = q.WorkStepEntities.OrderBy(r => r.WorkStepNumber).ToList());
            //循环遍历，往Node里面赋值
            foreach (var item in processesList)
            {
                AssignmentTreeOutput tree = new AssignmentTreeOutput();
                tree.Id = item.Id;
                tree.ParentId = NodeId;
                tree.NodeDrawingNo = "工序" + item.ProcessesSequence.ToString() + " ";
                tree.NodeName = item.ProcessesName;
                tree.IsRelation = 0;
                tree.NodeLevel = 8;
                tree.OutboundStatusDesc = GetEnumDesc(item.OutboundState);
                //查询工步
                foreach (var witem in item.WorkStepEntities)
                {
                    AssignmentTreeOutput wtree = new AssignmentTreeOutput();
                    wtree.Id = witem.Id;
                    wtree.ParentId = item.Id;
                    wtree.NodeDrawingNo = "工步" + item.ProcessesSequence.ToString();// + "-"+ witem.WorkStepNumber.ToString();
                    wtree.NodeName = witem.WorkStepNumber.ToString();//witem.WorkStepName  这个值数据库有问题
                    wtree.IsRelation = 0;
                    wtree.NodeLevel = 9;
                    wtree.OutboundStatusDesc = GetEnumDesc(witem.OutboundState);
                    tree.TreeList.Add(wtree);
                }
                treeNodeDto.TreeList.Add(tree);
            }
        }
        /// <summary>
        /// 默认排配
        /// </summary>
        /// <param name="input"></param>
        public ResultMessage DefaultArrangement(DefaultArrangementInput input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                if (input.StartTime != null)
                {
                    string realSrartTime = input.StartTime.Value.Date.ToString();
                    input.StartTime = Convert.ToDateTime(realSrartTime);
                }
                if (input.EndTime != null)
                {
                    var realEndTime = input.EndTime.Value.ToShortDateString().ToString();
                    input.EndTime = Convert.ToDateTime(realEndTime + " " + "23:59:59");
                }
                int route = RouteType(input.NodeId);
                var bopDesc = _bopDescRepository.GetAll().Where(d => d.Id == input.BopDescId).FirstOrDefault();
                if (bopDesc == null)
                {
                    resultMessage.code = 0;
                    return resultMessage;
                }
                Dictionary<Guid, decimal> mapHour = new Dictionary<Guid, decimal>();
                List<ProductionScheduler> schedulers = new List<ProductionScheduler>();
                List<CriticalPath> criticals = new List<CriticalPath>();
                CriticalPath critical = new CriticalPath();
                critical.Way = "";
                critical.ComputeHour = 0;
                //根据节点类型 然后排配时间
                switch (route)
                {
                    case 1:

                    case 2:
                        var bopNodes = _bopNodeRepository.GetAll().Where(d => d.ParentId == input.NodeId).OrderBy(d => d.CreationTime).ToList();
                        if (route == 1)
                        {
                            var tempBopDesc = _bopDescRepository.Get(input.BopDescId);
                            
                            tempBopDesc.StartTime = input.StartTime;
                            tempBopDesc.EndTime = input.EndTime;
                            _bopDescRepository.Update(tempBopDesc);
                        }
                        if (route == 2)
                        {
                            var tempBopNode = _bopNodeRepository.Get(input.NodeId);
                            tempBopNode.StartTime = input.StartTime;
                            tempBopNode.EndTime = input.EndTime;
                            _bopNodeRepository.Update(tempBopNode);
                        }
                        if (bopNodes.Count() > 0)
                        {
                            var lineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                            schedulers = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).ToList();
                            for (int i = 0; i < bopNodes.Count; i++)
                            {
                                mapHour.Add(bopNodes[i].Id, bopNodes[i].WorkingHour);
                            }
                            CriticalRecursion(lineList, mapHour, input.NodeId, criticals, critical, schedulers, input.EndTime.Value, null);
                            foreach (var item in schedulers)
                            {
                                if (item.ProductingStatus == ProductingStatus.已完成)
                                {
                                    resultMessage.code = 1;
                                    resultMessage.Message = "存在已完成的下发任务,无法默认排配!";
                                    return resultMessage;
                                    //throw new UserFriendlyException("存在已完成的下发任务,无法默认排配!");
                                }
                                _productionSchedulerRepository.Update(item);
                            }

                        }
                        break;
                    case 3:
                        var bopNode = _bopNodeRepository.Get(input.NodeId);

                        bopNode.StartTime = input.StartTime;
                        bopNode.EndTime = input.EndTime;
                        _bopNodeRepository.Update(bopNode);
                        var techId = bopNode.TechniqueEntityId;
                        var proTemp = _processesEntityRepository.GetAll().Where(d => d.TechniqueEntityId == techId).OrderBy(d => d.ProcessesSequence).ToList();
                        if (proTemp.Count > 0)
                        {
                            var lineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                            schedulers = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).ToList();
                            for (int i = 0; i < proTemp.Count; i++)
                            {
                                mapHour.Add(proTemp[i].Id, proTemp[i].ProcessesWorking);
                            }
                            CriticalRecursion(lineList, mapHour, input.NodeId, criticals, critical, schedulers, input.EndTime.Value, null);
                            foreach (var item in schedulers)
                            {
                                if (item.ProductingStatus == ProductingStatus.已完成)
                                {
                                    resultMessage.code = 1;
                                    resultMessage.Message = "存在已完成的下发任务,无法默认排配!";
                                    return resultMessage;
                                    //throw new UserFriendlyException("存在已完成的下发任务,无法默认排配!");
                                }
                                _productionSchedulerRepository.Update(item);
                            }
                        }
                        break;
                    case 4:

                        var proceTemp = _processesEntityRepository.Get(input.NodeId);
                        if (input.StartTime != null)
                        {
                            proceTemp.StartTime = input.StartTime.Value;

                        }
                       
                        proceTemp.EndTime = input.EndTime.Value;
                        _processesEntityRepository.Update(proceTemp);

                        var workTemp = _workStepEntityRepository.GetAll().Where(d => d.ProcessesEntityId == input.NodeId).OrderBy(d => d.WorkStepNumber).ToList();

                        if (workTemp.Count > 0)
                        {
                            var lineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                            schedulers = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).ToList();
                            for (int i = 0; i < workTemp.Count; i++)
                            {
                                mapHour.Add(workTemp[i].Id, workTemp[i].WorkStepWorking);
                            }
                            CriticalRecursion(lineList, mapHour, input.NodeId, criticals, critical, schedulers, input.EndTime.Value, null);
                            foreach (var item in schedulers)
                            {
                                if (item.ProductingStatus == ProductingStatus.已完成)
                                {
                                    resultMessage.code = 1;
                                    resultMessage.Message = "存在已完成的下发任务,无法默认排配!";
                                    return resultMessage;
                                    //throw new UserFriendlyException("存在已完成的下发任务,无法默认排配!");
                                }
                                _productionSchedulerRepository.Update(item);
                            }
                        }
                        break;
                    default:
                        break;
                }
                _iOperationHistoryAppService.InsertOperationLog(input.NodeId, 8, 25, "默认排配节点" + input.NodeDesc);
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }
        /// <summary>
        /// 获取当前节点的计划时间
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        public string GetDateTimeDefault(Guid guid)
        {
            var schTemp = _productionSchedulerRepository.GetAll().Where(d => d.NodeId == guid).FirstOrDefault();
            if (schTemp != null)
            {
                var dt = schTemp.EndTime;
                if (dt != null)
                {
                    return dt.Value.ToShortDateString();
                }
                else
                {
                    return "";
                }
            }
            else
            {
                return "";
            }
        }


        public AssignmentDisplayOutput DisplayRoute(Guid NodeId)
        {
            AssignmentDisplayOutput displayOutput = new AssignmentDisplayOutput();
            int route = RouteType(NodeId);

            Dictionary<Guid, decimal> mapHour = new Dictionary<Guid, decimal>();
            List<ProductionScheduler> schedulers = new List<ProductionScheduler>();
            List<CriticalPath> criticals = new List<CriticalPath>();
            CriticalPath critical = new CriticalPath();
            critical.Way = "";
            critical.ComputeHour = 0;
            int count = 0;
            if (route == 1)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _bopDescRepository.Get(NodeId);
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";

                processNodeDto.Text = parentNode.ModelName;
                processNodeDto.NodeDrawingNo = parentNode.DrawingNo;
                processNodeDtos.Add(processNodeDto);
                var bopNodes = _bopNodeRepository.GetAll().Where(d => d.BopDescId == NodeId && d.ParentId == NodeId).OrderBy(d => d.CreationTime).ToList();
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr ==NodeId).ToList();
                foreach (var item in bopNodes)
                {
                    mapHour.Add(item.Id, item.WorkingHour);
                }
                CriticalRecursion(LineList, mapHour,NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(bopNodes);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
            
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
            }
            if (route == 2)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _bopNodeRepository.Get(NodeId);
              
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";
                processNodeDtos.Add(processNodeDto);
                var bopNodes = _bopNodeRepository.GetAllList(d => d.ParentId == NodeId);
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr ==NodeId).ToList();
                foreach (var item in bopNodes)
                {
                    mapHour.Add(item.Id, item.WorkingHour);
                }
                CriticalRecursion(LineList, mapHour, NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(bopNodes);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
            
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
            }
            if (route == 3)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _bopNodeRepository.Get(NodeId);
             
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";
                processNodeDtos.Add(processNodeDto);
                var techTemp = _bopNodeRepository.FirstOrDefault(d => d.Id == NodeId);
                var techId = techTemp.TechniqueEntityId;
                var tech = _techniqueEntityRepository.FirstOrDefault(d => d.Id == techId);
                var processList = _processesEntityRepository.GetAllList(d => d.TechniqueEntityId == techId);
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr == NodeId).ToList();
                foreach (var item in processList)
                {
                    mapHour.Add(item.Id, item.ProcessesWorking);
                }
                CriticalRecursion(LineList, mapHour, NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(processList);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
            }
            if (route == 4)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _processesEntityRepository.Get(NodeId);
                var tech = _techniqueEntityRepository.Get(parentNode.TechniqueEntityId);
             
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";
                processNodeDtos.Add(processNodeDto);
                var workList = _workStepEntityRepository.GetAllList(d => d.ProcessesEntityId == NodeId);
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr == NodeId).ToList();
                foreach (var item in workList)
                {
                    mapHour.Add(item.Id, item.WorkStepWorking);
                }
                CriticalRecursion(LineList, mapHour, NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(workList);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
              
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
            }
            return displayOutput;
        }

        /// <summary>
        ///展示节点
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public AssignmentDisplayOutput GetNodePlanDetails(PlanInput input)
        {
            AssignmentDisplayOutput displayOutput = new AssignmentDisplayOutput();
            int route = RouteType(input.NodeId);

            Dictionary<Guid, decimal> mapHour = new Dictionary<Guid, decimal>();
            List<ProductionScheduler> schedulers = new List<ProductionScheduler>();
            List<CriticalPath> criticals = new List<CriticalPath>();
            CriticalPath critical = new CriticalPath();
            critical.Way = "";
            critical.ComputeHour = 0;
            var loadQuery = _loadPieceRepository.GetAll();
            var stockContent = _storeStockContentRepsitory.GetAll();
            int count = 0;
            if (route == 1)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _bopDescRepository.Get(input.NodeId);
                // 展示工艺路线信息
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";
                processNodeDto.Text = parentNode.ModelName;
                processNodeDto.NodeDrawingNo = parentNode.DrawingNo;
                processNodeDtos.Add(processNodeDto);
                var bopNodes = _bopNodeRepository.GetAll().Where(d => d.BopDescId == input.NodeId && d.ParentId == input.NodeId).OrderBy(d => d.CreationTime).ToList();
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                foreach (var item in bopNodes)
                {
                    mapHour.Add(item.Id, item.WorkingHour);
                }
                //计算关键路径
                CriticalRecursion(LineList, mapHour, input.NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                //获取最大时间的关键路径
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(bopNodes);
                //关键路径 展示路线标红
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
            
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;

                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
                var temp = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).OrderBy(d=>d.Sort).ToList();
                //有计划查找后 直接更新展示  没有的话 新增后展示
                if (temp.Count() == 0)
                {
                    for (int i = 0; i < bopNodes.Count; i++)
                    { 
                        //统计配套状态  
                        // 先获取 所有 装入件明细表的 配套数据 然后计算配套状态
                        int PreSuiteStock = 0;
                        int canPreSuite = 0;
                        var totalMaterial = _bomAnalyseAppServiceRepository.GetExternalCall(bopNodes[i].NodeName, bopNodes[i].NodeDrawingNo, parentNode.ModelId,parentNode.LotNoId);
                        PreSuiteStock = totalMaterial.Sum(d => d.PreSuiteStockAll);
                        
                        string AssortStateDesc = "";
                        var techQuery = _bopNodeRepository.GetAll().Where(d => d.NodeCode.StartsWith(bopNodes[i].NodeCode)).Where(d => d.TechniqueEntityId != null).Select(d => d.TechniqueEntityId).ToList();
                        if (techQuery.Count > 0)
                        {
                            var workIds = from cc in _workStepEntityRepository.GetAll()
                                          join mm in techQuery on cc.TechniqueEntityId equals mm
                                          select cc.Id;
                            // _workStepEntityRepository.GetAll().Where(d => techQuery.Contains(d.TechniqueEntityId)).Select(d => d.Id);

                            var loadList = (from cc in loadQuery
                                            join mm in workIds on cc.WorkStepEntityId equals mm
                                            select cc);
                                //loadQuery.Where(d => workIds.Contains(d.WorkStepEntityId));
                            int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                            var loadIds = loadList.Select(d => d.Id);
                            int SuiteStock = 0;
                            if (loadList.Count() > 0)
                            {
                                SuiteStock = (from cc in stockContent
                                              join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                              where cc.IsSuit == IsSuits.是
                                              select cc).Count();//配套数量
                            }
                           
                            canPreSuite = PreSuiteStock - SuiteStock;
                            //int PreSuiteStock = stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsPreSuit == IsSuits.是);//预配套
                            AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock, canPreSuite);
                        }
                        ProductionScheduler productionScheduler = new ProductionScheduler();
                        productionScheduler.Id = Guid.NewGuid();
                        productionScheduler.ParentId = input.NodeId;
                        productionScheduler.NodeId = bopNodes[i].Id;
                        productionScheduler.Sort = i + 1;
                        productionScheduler.Model = parentNode.Model;
                        productionScheduler.LotNo = parentNode.LotNo;
                        productionScheduler.ModelId = parentNode.ModelId;
                        productionScheduler.LotNoId = parentNode.LotNoId;
                        productionScheduler.DrawingNo = bopNodes[i].NodeDrawingNo;
                        productionScheduler.ProductionName = bopNodes[i].NodeName;
                        productionScheduler.WorkingHour = bopNodes[i].WorkingHour;
                        productionScheduler.PerformanceHour = 0;//默认绩效工时等于工时
                        productionScheduler.MatchingCondition = AssortStateDesc;
                        productionScheduler.ProductingStatus = ProductingStatus.已创建;
                        productionScheduler.ArrangementTime = DateTime.Now;
                        productionScheduler.DispatcherId = GetCurrentUser().Id;
                        productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                        _productionSchedulerRepository.Insert(productionScheduler);
                        temp.Add(productionScheduler);
                    }
                    count = bopNodes.Count;
                }
                else 
                {
                    count = temp.Count();
                    for (int i = 0; i < bopNodes.Count; i++)
                    {
                        int PreSuiteStock = 0;
                        int canPreSuite = 0;

                        var totalMaterial = _bomAnalyseAppServiceRepository.GetExternalCall(bopNodes[i].NodeName, bopNodes[i].NodeDrawingNo, parentNode.ModelId, parentNode.LotNoId);
                        PreSuiteStock = totalMaterial.Sum(d => d.PreSuiteStockAll);
                       

                        string AssortStateDesc = "";
                        var techQuery = _bopNodeRepository.GetAll().Where(d => d.NodeCode.StartsWith(bopNodes[i].NodeCode)).Where(d => d.TechniqueEntityId != null).Select(d => d.TechniqueEntityId).ToList();
                        if (techQuery.Count > 0)
                        {
                            var workIds = from cc in _workStepEntityRepository.GetAll()
                                          join mm in techQuery on cc.TechniqueEntityId equals mm
                                          select cc.Id;
                           // _workStepEntityRepository.GetAll().Where(d => techQuery.Contains(d.TechniqueEntityId)).Select(d => d.Id);
                            var loadList = (from cc in loadQuery
                                            join mm in workIds on cc.WorkStepEntityId equals mm
                                            select cc);
                                //loadQuery.Where(d => workIds.Contains(d.WorkStepEntityId));
                            int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                            var loadIds = loadList.Select(d => d.Id);
                            int SuiteStock = 0;
                            if (loadIds.Count() > 0)
                            {
                                SuiteStock = (from cc in stockContent
                                              join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                              where cc.IsSuit == IsSuits.是
                                              select cc).Count();//配套数量

                            }
                            canPreSuite = PreSuiteStock - SuiteStock;
                            AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock, canPreSuite);
                        }
                        var pro = temp.Where(d => d.NodeId == bopNodes[i].Id).FirstOrDefault();
                        if (pro != null)
                        {
                            pro.MatchingCondition = AssortStateDesc;
                            pro.WorkingHour = bopNodes[i].WorkingHour;
                            pro.Sort = i + 1;
                            _productionSchedulerRepository.Update(pro);
                        }
                        else
                        {
                            ProductionScheduler productionScheduler = new ProductionScheduler();
                            productionScheduler.Id = Guid.NewGuid();
                            productionScheduler.ParentId = input.NodeId;
                            productionScheduler.NodeId = bopNodes[i].Id;
                            productionScheduler.Sort = i + 1;
                            productionScheduler.Model = parentNode.Model;
                            productionScheduler.LotNo = parentNode.LotNo;
                            productionScheduler.ModelId = parentNode.ModelId;
                            productionScheduler.LotNoId = parentNode.LotNoId;
                            productionScheduler.DrawingNo = bopNodes[i].NodeDrawingNo;
                            productionScheduler.ProductionName = bopNodes[i].NodeName;
                            productionScheduler.WorkingHour = bopNodes[i].WorkingHour;
                            productionScheduler.MatchingCondition = AssortStateDesc;
                            productionScheduler.ProductingStatus = ProductingStatus.已创建;
                            productionScheduler.ArrangementTime = DateTime.Now;
                            productionScheduler.DispatcherId = GetCurrentUser().Id;
                            productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            _productionSchedulerRepository.Insert(productionScheduler);
                            temp.Add(productionScheduler);
                        }
                    }
                }
                var proTemp = temp.OrderBy(d=>d.Sort).AsQueryable().PageBy(input);
                displayOutput.Productions = ObjectMapper.Map<List<ProductionSchedulerOutput>>(proTemp);
                displayOutput.StartTime = parentNode.StartTime;
                displayOutput.EndTime = parentNode.EndTime;
            }
            if (route == 2)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _bopNodeRepository.Get(input.NodeId);
              
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";
                processNodeDtos.Add(processNodeDto);
                var bopNodes = _bopNodeRepository.GetAll().Where(d => d.ParentId == input.NodeId).OrderBy(d=>d.CreationTime).ToList();
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                foreach (var item in bopNodes)
                {
                    mapHour.Add(item.Id, item.WorkingHour);
                }
                CriticalRecursion(LineList, mapHour, input.NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(bopNodes);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                processNodeDto.Color = "black";
                                processNodeDto.Fill = "pink";
                                processNodeDto.Size = 0;
                                processNodeDto.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
             
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
                var temp = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).ToList();
                var bopDescTemp = _bopDescRepository.Get(input.BopDescId);
                if (temp.Count() == 0)
                {
                    for (int i = 0; i < bopNodes.Count; i++)
                    {
                        int PreSuiteStock = 0;
                        int canPreSuite = 0;

                        var coreGrade = _bopNodeRepository.GetAll().Where(d => d.NodeCode == bopNodes[i].ParentCode.Substring(0, 3) && d.BopDescId == bopNodes[i].BopDescId).FirstOrDefault();
                        if (coreGrade != null)
                        {
                            var totalMaterial = _bomAnalyseAppServiceRepository.GetExternalCall(coreGrade.NodeName, coreGrade.NodeDrawingNo, bopDescTemp.ModelId, bopDescTemp.LotNoId);
                            PreSuiteStock = totalMaterial.Sum(d => d.PreSuiteStockAll);
                            canPreSuite = totalMaterial.Sum(d => d.DifferenceCount);
                        }
                        else
                        {
                            throw new UserFriendlyException("未找到该节点对应的芯级!");
                        }

                        #region 配套状态
                        string AssortStateDesc = "";
                        var techQuery = _bopNodeRepository.GetAll().Where(d => d.NodeCode.StartsWith(bopNodes[i].NodeCode)).Where(d => d.TechniqueEntityId != null).Select(d => d.TechniqueEntityId).ToList();
                        if (techQuery.Count > 0)
                        {
                            var workIds = from cc in _workStepEntityRepository.GetAll()
                                          join mm in techQuery on cc.TechniqueEntityId equals mm
                                          select cc.Id;
                            //_workStepEntityRepository.GetAll().Where(d => techQuery.Contains(d.TechniqueEntityId)).Select(d => d.Id);
                            var loadList = (from cc in loadQuery
                                            join mm in workIds on cc.WorkStepEntityId equals mm
                                            select cc);
                                //loadQuery.Where(d => workIds.Contains(d.WorkStepEntityId));
                            int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                            var loadIds = loadList.Select(d => d.Id);
                            int SuiteStock = 0;
                            if (loadIds.Count() > 0)
                            {
                                SuiteStock = (from cc in stockContent
                                              join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                              where cc.IsSuit == IsSuits.是
                                              select cc).Count();//配套数量
                            }
                            //int PreSuiteStock = stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsPreSuit == IsSuits.是);//预配套
                            AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock, canPreSuite);
                        }

                        #endregion
                        ProductionScheduler productionScheduler = new ProductionScheduler();
                        productionScheduler.Id = Guid.NewGuid();
                        productionScheduler.ParentId = input.NodeId;
                        productionScheduler.NodeId = bopNodes[i].Id;
                        productionScheduler.Sort = i + 1;
                        productionScheduler.Model = bopDescTemp.Model;
                        productionScheduler.LotNo = bopDescTemp.LotNo;
                        productionScheduler.ModelId = bopDescTemp.ModelId;
                        productionScheduler.LotNoId = bopDescTemp.LotNoId;
                        productionScheduler.DrawingNo = bopNodes[i].NodeDrawingNo;
                        productionScheduler.ProductionName = bopNodes[i].NodeName;
                        productionScheduler.WorkingHour = bopNodes[i].WorkingHour;
                        productionScheduler.PerformanceHour = 0;//默认绩效工时等于工时
                        productionScheduler.MatchingCondition = AssortStateDesc;// 配套状况从曲冰接口获取
                        productionScheduler.ProductingStatus = ProductingStatus.已创建;
                        productionScheduler.ArrangementTime = DateTime.Now;
                        productionScheduler.DispatcherId = GetCurrentUser().Id;
                        productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                        _productionSchedulerRepository.Insert(productionScheduler);
                        temp.Add(productionScheduler);


                    }
                    count = bopNodes.Count;
                }
                else
                {
                    count = temp.Count();

                    for (int i = 0; i < bopNodes.Count; i++)
                    {
                        int PreSuiteStock = 0;
                        int canPreSuite = 0;

                        var coreGrade = _bopNodeRepository.GetAll().Where(d => d.NodeCode == bopNodes[i].ParentCode.Substring(0, 3) && d.BopDescId == bopNodes[i].BopDescId).FirstOrDefault();
                        if (coreGrade != null)
                        {
                            var totalMaterial = _bomAnalyseAppServiceRepository.GetExternalCall(coreGrade.NodeName, coreGrade.NodeDrawingNo, bopDescTemp.ModelId, bopDescTemp.LotNoId);
                            PreSuiteStock = totalMaterial.Sum(d => d.PreSuiteStockAll);
                            canPreSuite = totalMaterial.Sum(d => d.DifferenceCount);
                        }
                        else
                        {
                            throw new UserFriendlyException("未找到该节点对应的芯级!");
                        }
                        string AssortStateDesc = "";
                        var techQuery = _bopNodeRepository.GetAll().Where(d => d.NodeCode.StartsWith(bopNodes[i].NodeCode)).Where(d => d.TechniqueEntityId != null).Select(d => d.TechniqueEntityId).ToList();
                        if (techQuery.Count > 0)
                        {
                            var workIds = from cc in _workStepEntityRepository.GetAll()
                                          join mm in techQuery on cc.TechniqueEntityId equals mm
                                          select cc.Id;
                            //_workStepEntityRepository.GetAll().Where(d => techQuery.Contains(d.TechniqueEntityId)).Select(d => d.Id);
                            var loadList = (from cc in loadQuery
                                            join mm in workIds on cc.WorkStepEntityId equals mm
                                            select cc);
                                // loadQuery.Where(d => workIds.Contains(d.WorkStepEntityId));
                            int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                            var loadIds = loadList.Select(d => d.Id);
                            int SuiteStock = 0;
                            if (loadIds.Count() > 0)
                            {
                                SuiteStock = (from cc in stockContent
                                              join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                              where cc.IsSuit == IsSuits.是
                                              select cc).Count();//配套数量
                            }
                            //stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsSuit == StoreManagement.StoragePut.StoreStockContent.IsSuits.是);//配套数量
                          
                            AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock, canPreSuite);
                        }
                        var  pro=  temp.Where(d => d.NodeId == bopNodes[i].Id).FirstOrDefault();
                        if (pro != null)
                        {
                            pro.MatchingCondition = AssortStateDesc;
                            pro.Sort = i + 1;
                            pro.WorkingHour = bopNodes[i].WorkingHour;
                            _productionSchedulerRepository.Update(pro);
                        }
                        else
                        {
                            ProductionScheduler productionScheduler = new ProductionScheduler();
                            productionScheduler.Id = Guid.NewGuid();
                            productionScheduler.ParentId = input.NodeId;
                            productionScheduler.NodeId = bopNodes[i].Id;
                            productionScheduler.Sort = i + 1;
                            productionScheduler.Model = bopDescTemp.Model;
                            productionScheduler.LotNo = bopDescTemp.LotNo;
                            productionScheduler.ModelId = bopDescTemp.ModelId;
                            productionScheduler.LotNoId = bopDescTemp.LotNoId;
                            productionScheduler.DrawingNo = bopNodes[i].NodeDrawingNo;
                            productionScheduler.ProductionName = bopNodes[i].NodeName;
                            productionScheduler.WorkingHour = bopNodes[i].WorkingHour;
                       
                            productionScheduler.MatchingCondition = AssortStateDesc;// 配套状况从曲冰接口获取
                            productionScheduler.ProductingStatus = ProductingStatus.已创建;
                            productionScheduler.ArrangementTime = DateTime.Now;
                            productionScheduler.DispatcherId = GetCurrentUser().Id;
                            productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            _productionSchedulerRepository.Insert(productionScheduler);
                            temp.Add(productionScheduler);
                        }
                    }

                }

                var proTemp = temp.OrderBy(d=>d.Sort).AsQueryable().PageBy(input);
                displayOutput.Productions = ObjectMapper.Map<List<ProductionSchedulerOutput>>(proTemp);
                displayOutput.StartTime = parentNode.StartTime;
                displayOutput.EndTime = parentNode.EndTime;
            }
            if (route == 3)
            {

               
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _bopNodeRepository.Get(input.NodeId);
                var bopDesc = _bopDescRepository.Get(parentNode.BopDescId);
                int PreSuiteStock = 0;
                int canPreSuite = 0;
                var coreGradeNode = _bopNodeRepository.GetAll().Where(d => d.NodeCode == parentNode.ParentCode.Substring(0, 3) && d.BopDescId == parentNode.BopDescId).FirstOrDefault();
                if (coreGradeNode != null)
                {
                    var totalMaterial = _bomAnalyseAppServiceRepository.GetExternalCall(coreGradeNode.NodeName, coreGradeNode.NodeDrawingNo, bopDesc.ModelId, bopDesc.LotNoId);
                    PreSuiteStock = totalMaterial.Sum(d => d.PreSuiteStockAll);
                    canPreSuite = totalMaterial.Sum(d => d.DifferenceCount);
                }
                else
                {
                    throw new UserFriendlyException("未找到该节点对应的芯级!");
                }
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";

                processNodeDtos.Add(processNodeDto);
                var techTemp = _bopNodeRepository.FirstOrDefault(d => d.Id == input.NodeId);
                var techId = techTemp.TechniqueEntityId;
                var tech = _techniqueEntityRepository.FirstOrDefault(d => d.Id == techId);
                var processList = _processesEntityRepository.GetAll().Where(d => d.TechniqueEntityId == techId).OrderBy(d=>d.ProcessesSequence).ToList();
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                foreach (var item in processList)
                {
                    mapHour.Add(item.Id, item.ProcessesWorking);
                }
                CriticalRecursion(LineList, mapHour, input.NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(processList);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                           
                        }
                    }
                }
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
                var temp = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).ToList();
                var bopDescTemp = _bopDescRepository.Get(input.BopDescId);
                if (temp.Count() == 0)
                {
                    for (int i = 0; i < processList.Count; i++)
                    {
                        #region 配套状态
                        string AssortStateDesc = "";
                        var workList = _workStepEntityRepository.GetAll().Where(d => d.ProcessesEntityId == processList[i].Id).OrderBy(d=>d.WorkStepNumber).ToList();
                        if (workList.Count() > 0)
                        {
                            var workIds = workList.Select(d => d.Id);
                            var loadList = (from cc in loadQuery
                                            join mm in workIds on cc.WorkStepEntityId equals mm
                                            select cc);


                               // loadQuery.Where(d => workIds.Contains(d.WorkStepEntityId));
                            int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                            var loadIds = loadList.Select(d => d.Id);

                            int SuiteStock = 0;

                            if (loadIds.Count() > 0)
                            {
                                SuiteStock = (from cc in stockContent
                                              join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                              where cc.IsSuit == IsSuits.是
                                              select cc).Count();//配套数量
                            }
                            //stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsSuit == StoreManagement.StoragePut.StoreStockContent.IsSuits.是);//配套数量
                            //int PreSuiteStock = stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsPreSuit == IsSuits.是);//预配套

                            AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock,canPreSuite);
                        }
                        #endregion
                        ProductionScheduler productionScheduler = new ProductionScheduler();
                        productionScheduler.Id = Guid.NewGuid();
                        productionScheduler.ParentId = input.NodeId;
                        productionScheduler.NodeId = processList[i].Id;
                        productionScheduler.Sort = i + 1;
                        productionScheduler.Model = bopDescTemp.Model;
                        productionScheduler.LotNo = bopDescTemp.LotNo;
                        productionScheduler.ModelId = bopDescTemp.ModelId;
                        productionScheduler.LotNoId = bopDescTemp.LotNoId;
                        productionScheduler.DrawingNo = "工序" + processList[i].ProcessesSequence;
                        productionScheduler.ProductionName = processList[i].ProcessesName;
                        productionScheduler.TechniqueName = tech.TechniqueName;
                        productionScheduler.TechniqueNumber = tech.TechniqueNumber;
                        productionScheduler.WorkingHour = processList[i].ProcessesWorking;
                        productionScheduler.PerformanceHour = 0;//默认绩效工时等于工时
                        productionScheduler.MatchingCondition = AssortStateDesc;// 配套状况从曲冰接口获取
                        productionScheduler.ProductingStatus = ProductingStatus.已创建;
                        productionScheduler.ArrangementTime = DateTime.Now;
                        productionScheduler.DispatcherId = GetCurrentUser().Id;
                        productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                        _productionSchedulerRepository.Insert(productionScheduler);
                        temp.Add(productionScheduler);

                        for (int j = 0; j < workList.Count; j++)
                        {
                            ProductionScheduler workScheduler = new ProductionScheduler();
                            workScheduler.Id = Guid.NewGuid();
                            workScheduler.NodeId = workList[j].Id;
                            workScheduler.ParentId = workList[j].ProcessesEntityId;
                            workScheduler.Sort = j + 1;
                            workScheduler.Model = bopDescTemp.Model;
                            workScheduler.LotNo = bopDescTemp.LotNo;
                            workScheduler.ModelId = bopDescTemp.ModelId;
                            workScheduler.LotNoId = bopDescTemp.LotNoId;
                            workScheduler.DrawingNo = "工序" + processList[i].ProcessesSequence;
                            workScheduler.ProductionName = processList[i].ProcessesName;
                            workScheduler.ProcessesEntityId = parentNode.Id;
                            workScheduler.WorkStepDrawingNo = "工步" + processList[i].ProcessesSequence + "-" + workList[j].WorkStepNumber.ToString();
                            workScheduler.WorkStepName = workList[j].WorkStepName;
                            workScheduler.TechniqueName = tech.TechniqueName;
                            workScheduler.TechniqueNumber = tech.TechniqueNumber;
                            workScheduler.WorkingHour = workList[j].WorkStepWorking;
                            workScheduler.PerformanceHour = 0;//默认绩效工时等于工时
                            workScheduler.MatchingCondition = "";// 配套状况从曲冰接口获取
                            workScheduler.ProductingStatus = ProductingStatus.已创建;
                            workScheduler.ArrangementTime = DateTime.Now;
                            workScheduler.DispatcherId = GetCurrentUser().Id;
                            workScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            _productionSchedulerRepository.Insert(workScheduler);
                        }

                    }
                    count = processList.Count;
                }
                else
                {
                    count = temp.Count();
                    for (int i = 0; i < processList.Count; i++)
                    {
                        string AssortStateDesc = "";
                        var workList = _workStepEntityRepository.GetAll().Where(d => d.ProcessesEntityId == processList[i].Id).OrderBy(d=>d.WorkStepNumber).ToList();
                        if (workList.Count() > 0)
                        {
                            var workIds = workList.Select(d => d.Id);
                            var loadList = (from cc in loadQuery
                                            join mm in workIds on cc.WorkStepEntityId equals mm
                                            select cc);
                                //loadQuery.Where(d => workIds.Contains(d.WorkStepEntityId));
                            int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                            var loadIds = loadList.Select(d => d.Id);
                            int SuiteStock = 0;
                           
                            if (loadIds.Count() > 0)
                            {
                                SuiteStock = (from cc in stockContent
                                              join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                              where cc.IsSuit == IsSuits.是
                                              select cc).Count();//配套数量
                            }
                            //stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsSuit == StoreManagement.StoragePut.StoreStockContent.IsSuits.是);//配套数量
                            //int PreSuiteStock = stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsPreSuit == IsSuits.是);//预配套
                            AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock, canPreSuite);
                        }
                        var pro = temp.Where(d => d.NodeId == processList[i].Id).FirstOrDefault();
                        if (pro != null)
                        {
                            pro.MatchingCondition = AssortStateDesc;
                            pro.Sort = i + 1;
                            pro.WorkingHour = processList[i].ProcessesWorking;
                            _productionSchedulerRepository.Update(pro);
                        }
                        else
                        {
                            ProductionScheduler productionScheduler = new ProductionScheduler();
                            productionScheduler.Id = Guid.NewGuid();
                            productionScheduler.ParentId = input.NodeId;
                            productionScheduler.NodeId = processList[i].Id;
                            productionScheduler.Sort = i + 1;
                            productionScheduler.Model = bopDescTemp.Model;
                            productionScheduler.LotNo = bopDescTemp.LotNo;
                            productionScheduler.ModelId = bopDescTemp.ModelId;
                            productionScheduler.LotNoId = bopDescTemp.LotNoId;
                            productionScheduler.DrawingNo = "工序" + processList[i].ProcessesSequence;
                            productionScheduler.ProductionName = processList[i].ProcessesName;
                            productionScheduler.TechniqueName = tech.TechniqueName;
                            productionScheduler.TechniqueNumber = tech.TechniqueNumber;
                            productionScheduler.WorkingHour = processList[i].ProcessesWorking;
                          
                            productionScheduler.MatchingCondition = AssortStateDesc;// 配套状况从曲冰接口获取
                            productionScheduler.ProductingStatus = ProductingStatus.已创建;
                            productionScheduler.ArrangementTime = DateTime.Now;
                            productionScheduler.DispatcherId = GetCurrentUser().Id;
                            productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            _productionSchedulerRepository.Insert(productionScheduler);
                            temp.Add(productionScheduler);

                            for (int j = 0; j < workList.Count; j++)
                            {
                                ProductionScheduler workScheduler = new ProductionScheduler();
                                workScheduler.Id = Guid.NewGuid();
                                workScheduler.NodeId = workList[j].Id;
                                workScheduler.ParentId = workList[j].ProcessesEntityId;
                                workScheduler.Sort = j + 1;
                                workScheduler.Model = bopDescTemp.Model;
                                workScheduler.LotNo = bopDescTemp.LotNo;
                                workScheduler.ModelId = bopDescTemp.ModelId;
                                workScheduler.LotNoId = bopDescTemp.LotNoId;
                                workScheduler.DrawingNo = "工序" + processList[i].ProcessesSequence;
                                workScheduler.ProductionName = processList[i].ProcessesName;
                                workScheduler.ProcessesEntityId = parentNode.Id;
                                workScheduler.WorkStepDrawingNo = "工步" + processList[i].ProcessesSequence + "-" + workList[j].WorkStepNumber.ToString();
                                workScheduler.WorkStepName = workList[j].WorkStepName;
                                workScheduler.TechniqueName = tech.TechniqueName;
                                workScheduler.TechniqueNumber = tech.TechniqueNumber;
                                workScheduler.WorkingHour = workList[j].WorkStepWorking;
                            
                                workScheduler.MatchingCondition = "";// 配套状况从曲冰接口获取
                                workScheduler.ProductingStatus = ProductingStatus.已创建;
                                workScheduler.ArrangementTime = DateTime.Now;
                                workScheduler.DispatcherId = GetCurrentUser().Id;
                                workScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                                _productionSchedulerRepository.Insert(workScheduler);
                            }
                        }
                    }

                }
                var proTemp = temp.OrderBy(d=>d.Sort).AsQueryable().PageBy(input);
                displayOutput.Productions = ObjectMapper.Map<List<ProductionSchedulerOutput>>(proTemp);
                displayOutput.StartTime = parentNode.StartTime;
                displayOutput.EndTime = parentNode.EndTime;
            }
            if (route == 4)
            {
                List<ProcessNodeDto> processNodeDtos = new List<ProcessNodeDto>();
                var parentNode = _processesEntityRepository.Get(input.NodeId);
                var tech = _techniqueEntityRepository.Get(parentNode.TechniqueEntityId);

                var coreNodeInput = (from tempc in _bopNodeRepository.GetAll().Where(d=>d.TechniqueEntityId== tech.Id)
                                     select new
                                     {
                                         ParentCode = tempc.ParentCode.Substring(0, 3),
                                         BopDescId = tempc.BopDescId
                                     }).FirstOrDefault();
                int PreSuiteStock = 0;
                int canPreSuite = 0;
                var coreNode = _bopNodeRepository.GetAll().Where(d => d.NodeCode == coreNodeInput.ParentCode && d.BopDescId == coreNodeInput.BopDescId).FirstOrDefault();
                if (coreNode != null)
                {
                    var bopDesc = _bopDescRepository.Get(coreNode.BopDescId);
                    var tempMaterialStatistics = _bomAnalyseAppServiceRepository.GetExternalCall(coreNode.NodeName, coreNode.NodeDrawingNo, bopDesc.ModelId,bopDesc.LotNoId);
                    PreSuiteStock = tempMaterialStatistics.Sum(d => d.PreSuiteStockAll);
                    canPreSuite= tempMaterialStatistics.Sum(d => d.DifferenceCount);
                }


              
                var processNodeDto = ObjectMapper.Map<ProcessNodeDto>(parentNode);
                processNodeDto.Color = "black";
                processNodeDto.Fill = "pink";
                processNodeDto.Size = 0;
                processNodeDto.Figure = "RoundedRectangle";
                processNodeDtos.Add(processNodeDto);
                var workList = _workStepEntityRepository.GetAll().Where(d => d.ProcessesEntityId == input.NodeId).OrderBy(d=>d.WorkStepNumber).ToList();
                var LineList = _processLineRepository.GetAll().Where(d => d.PPtr == input.NodeId).ToList();
                foreach (var item in workList)
                {
                    mapHour.Add(item.Id, item.WorkStepWorking);
                }
                CriticalRecursion(LineList, mapHour, input.NodeId, criticals, critical, schedulers, DateTime.Now, null, 1);
                var maxHour = criticals.Max(d => d.ComputeHour);
                var tempHour = criticals.Where(d => d.ComputeHour == maxHour).Select(d => d.Way).ToList();
                var data = ObjectMapper.Map<List<ProcessNodeDto>>(workList);
                for (int i = 0; i < tempHour.Count; i++)
                {
                    if (tempHour[i].Length > 1)
                    {
                        string tempStr = tempHour[i].Substring(1);
                        var tempArray = tempStr.Split(',');
                        for (int j = 0; j < tempArray.Count(); j++)
                        {
                            Guid guid = new Guid(tempArray[j]);
                            var tempNode = data.Where(d => d.Key == guid).FirstOrDefault();
                            if (tempNode != null)
                            {
                                tempNode.Color = "black";
                                tempNode.Fill = "pink";
                                tempNode.Size = 0;
                                tempNode.Figure = "RoundedRectangle";
                            }
                        }
                    }
                }
             
                processNodeDtos.AddRange(data);
                displayOutput.ProcessNodeList = processNodeDtos;
                displayOutput.ProcessLineList = ObjectMapper.Map<List<ProcessLineDto>>(LineList);
                var temp = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == input.NodeId).ToList();
                var bopDescTemp = _bopDescRepository.Get(input.BopDescId);
           

                if (temp.Count() == 0)
                {
                    for (int i = 0; i < workList.Count; i++)
                    {
                        #region 配套状态
                        string AssortStateDesc = "";
                        var loadList = loadQuery.Where(d => d.WorkStepEntityId == workList[i].Id);
                        int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                        var loadIds = loadList.Select(d => d.Id);
                        int SuiteStock = 0;
                        if (loadIds.Count() > 0)
                        {
                            SuiteStock = (from cc in stockContent
                                          join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                          where cc.IsSuit == IsSuits.是
                                          select cc).Count();//配套数量
                        }
                        //stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsSuit == StoreManagement.StoragePut.StoreStockContent.IsSuits.是);//配套数量
                        // int PreSuiteStock = stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsPreSuit == IsSuits.是);//预配套
                        AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock,canPreSuite);
                        #endregion

                        ProductionScheduler productionScheduler = new ProductionScheduler();
                        productionScheduler.Id = Guid.NewGuid();
                        productionScheduler.NodeId = workList[i].Id;
                        productionScheduler.ParentId = input.NodeId;
                        productionScheduler.Sort = i + 1;
                        productionScheduler.Model = bopDescTemp.Model;
                        productionScheduler.LotNo = bopDescTemp.LotNo;
                        productionScheduler.ModelId = bopDescTemp.ModelId;
                        productionScheduler.LotNoId = bopDescTemp.LotNoId;
                        productionScheduler.DrawingNo = "工序" + parentNode.ProcessesSequence;
                        productionScheduler.ProductionName = parentNode.ProcessesName;
                        productionScheduler.ProcessesEntityId = parentNode.Id;
                        productionScheduler.WorkStepDrawingNo = "工步" + parentNode.ProcessesSequence + "-" + workList[i].WorkStepNumber.ToString();
                        productionScheduler.WorkStepName = workList[i].WorkStepName;
                        productionScheduler.TechniqueName = tech.TechniqueName;
                        productionScheduler.TechniqueNumber = tech.TechniqueNumber;
                        productionScheduler.WorkingHour = workList[i].WorkStepWorking;
                        productionScheduler.PerformanceHour = 0;//默认绩效工时等于工时
                        productionScheduler.MatchingCondition = AssortStateDesc;
                        productionScheduler.ProductingStatus = ProductingStatus.已创建;
                        productionScheduler.ArrangementTime = DateTime.Now;
                        productionScheduler.DispatcherId = GetCurrentUser().Id;
                        productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                        _productionSchedulerRepository.Insert(productionScheduler);
                        temp.Add(productionScheduler);
                    }
                    count = workList.Count;
                }
                else
                {
                    count = temp.Count();
                    for (int i = 0; i < workList.Count; i++)
                    {
                        string AssortStateDesc = "";
                        var loadList = loadQuery.Where(d => d.WorkStepEntityId == workList[i].Id);
                        int ProcessDosage = loadList.Sum(d => d.Number); //工艺用量
                        var loadIds = loadList.Select(d => d.Id);
                        int SuiteStock = 0;
                        //stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsSuit == StoreManagement.StoragePut.StoreStockContent.IsSuits.是);//配套数量
                        if (loadIds.Count() > 0)
                        {
                            SuiteStock = (from cc in stockContent
                                          join mm in loadIds on cc.LoadDetailsId.Value equals mm
                                          where cc.IsSuit == IsSuits.是
                                          select cc).Count();//配套数量
                        }
                        // int PreSuiteStock = stockContent.Count(d => loadIds.Contains(d.LoadDetailsId.Value) && d.IsPreSuit == IsSuits.是);//预配套
                        AssortStateDesc = GetAssortStateDesc(ProcessDosage, SuiteStock, PreSuiteStock,canPreSuite);
                        var pro = temp.Where(d => d.NodeId == workList[i].Id).FirstOrDefault();
                        if (pro != null)
                        {
                            pro.MatchingCondition = AssortStateDesc;
                            pro.WorkingHour = workList[i].WorkStepWorking;
                            _productionSchedulerRepository.Update(pro);
                        }
                        else
                        {
                            ProductionScheduler productionScheduler = new ProductionScheduler();
                            productionScheduler.Id = Guid.NewGuid();
                            productionScheduler.NodeId = workList[i].Id;
                            productionScheduler.ParentId = input.NodeId;
                            productionScheduler.Sort = i + 1;
                            productionScheduler.Model = bopDescTemp.Model;
                            productionScheduler.LotNo = bopDescTemp.LotNo;
                            productionScheduler.ModelId = bopDescTemp.ModelId;
                            productionScheduler.LotNoId = bopDescTemp.LotNoId;
                            productionScheduler.DrawingNo = "工序" + parentNode.ProcessesSequence;
                            productionScheduler.ProductionName = parentNode.ProcessesName;
                            productionScheduler.ProcessesEntityId = parentNode.Id;
                            productionScheduler.WorkStepDrawingNo = "工步" + parentNode.ProcessesSequence + "-" + workList[i].WorkStepNumber.ToString();
                            productionScheduler.WorkStepName = workList[i].WorkStepName;
                            productionScheduler.TechniqueName = tech.TechniqueName;
                            productionScheduler.TechniqueNumber = tech.TechniqueNumber;
                            productionScheduler.WorkingHour = workList[i].WorkStepWorking;
                          
                            productionScheduler.MatchingCondition = AssortStateDesc;
                            productionScheduler.ProductingStatus = ProductingStatus.已创建;
                            productionScheduler.ArrangementTime = DateTime.Now;
                            productionScheduler.DispatcherId = GetCurrentUser().Id;
                            productionScheduler.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            _productionSchedulerRepository.Insert(productionScheduler);
                            temp.Add(productionScheduler);
                        }
                    }
                }
                var proTemp = temp.OrderBy(d=>d.Sort).AsQueryable().PageBy(input);
                displayOutput.Productions = ObjectMapper.Map<List<ProductionSchedulerOutput>>(proTemp);
                displayOutput.StartTime = parentNode.StartTime;
                displayOutput.EndTime = parentNode.EndTime;
            }
            displayOutput.Count = count;
            return displayOutput;
        }
        /// <summary>
        /// 手动排配
        /// </summary>
        /// <param name="input"></param>
        public ResultMessage HandManage(HandManageInput input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                if (input.StartTime != null)
                {
                    string realSrartTime = input.StartTime.Value.Date.ToString();
                    input.StartTime = Convert.ToDateTime(realSrartTime);
                }
                if (input.EndTime != null)
                {
                    var realEndTime = input.EndTime.Value.ToShortDateString().ToString();
                    input.EndTime = Convert.ToDateTime(realEndTime + " " + "23:59:59");
                }

                if (input.GuidList == null)
                {
                    resultMessage.code = 0;
                    return resultMessage;
                }
                if (input.GuidList.Count > 0)
                {

                    var planList = _productionSchedulerRepository.GetAll().Where(d => input.GuidList.Contains(d.Id));
                    foreach (var item in input.GuidList)
                    {
                        var planTemp = planList.Where(d => d.Id == item).FirstOrDefault();
                        if (planTemp != null)
                        {
                            if (planTemp.ProductingStatus == ProductingStatus.已完成)
                            {
                                resultMessage.code = 1;
                                resultMessage.Message = "存在已完成的下发任务,无法手动排配!";
                                return resultMessage;
                                //throw new UserFriendlyException("存在已完成的下发任务,无法手动排配!");
                            }
                            if (input.StartTime != null)
                            {
                                planTemp.StartTime = input.StartTime;
                            }
                            if (input.EndTime != null)
                            {
                                planTemp.EndTime = input.EndTime;
                            }
                            planTemp.OrganizationUnitId = input.OrganizationUnitId;
                            planTemp.OrganizationUnitDesc = input.OrganizationUnitDesc;
                            planTemp.UserId = input.UserId;
                            planTemp.UserName = input.UserName;
                            planTemp.DispatcherId = GetCurrentUser().Id;
                            planTemp.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            planTemp.Remark = input.Remark;
                            planTemp.ArrangementTime = DateTime.Now;
                            _productionSchedulerRepository.Update(planTemp);
                            _iOperationHistoryAppService.InsertOperationLog(planTemp.Id, 8, 26, "手动排配节点" + planTemp.ProductionName);
                        }
                        else
                        {
                            resultMessage.code = 1;
                            resultMessage.Message = "传入数据有误!";
                            return resultMessage;
                            //throw new Exception("传入数据有误!");
                        }
                    }
                }
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }

        /// <summary>
        /// 下发任务
        /// </summary>
        /// <param name="guidList"></param>
        /// <returns></returns>
        public ResultMessage IssueTask(List<Guid> guidList)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                if (guidList == null)
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "下发任务失败！";
                    return resultMessage;
                }

                if (guidList.Count > 0)
                {
                    var planList = _productionSchedulerRepository.GetAll().Where(d => guidList.Contains(d.Id));

                    var tempQuery = from tempPro in _productionSchedulerRepository.GetAll() select tempPro;
                    foreach (var item in guidList)
                    {
                        var planTemp = planList.Where(d => d.Id == item).FirstOrDefault();
                        if (planTemp != null)
                        {
                            int route = RouteType(item);
                            if (route == 4)
                            {
                                var workIds = _workStepEntityRepository.GetAll().Where(d => d.ProcessesEntityId == item).Select(d => d.Id).ToList();
                                var tempIsure = tempQuery.Count(d => workIds.Contains(d.NodeId) && d.Issue == true);
                                if (tempIsure > 0)
                                {
                                    resultMessage.code = 1;
                                    resultMessage.Message = "该工序下已存在工步级下发任务!";
                                    return resultMessage;
                                    //throw new Exception("该工序下已存在工步级下发任务!");
                                }
                            }
                            else if (route == 5)
                            {
                                var process = _workStepEntityRepository.Get(item);
                                var tempIsure = tempQuery.Where(d => d.NodeId == process.ProcessesEntityId).FirstOrDefault();
                                if (tempIsure.Issue == true)
                                {
                                    resultMessage.code = 1;
                                    resultMessage.Message = "该工序上级已存在工序级下发任务!";
                                    return resultMessage;
                                    //throw new Exception("该工序上级已存在工序级下发任务!");
                                }
                            }
                            //Guid codeFormatId = Guid.Parse("59BC5C4B-1CF6-437C-A0BC-E0057075CD97");//暂时写死
                            planTemp.ProductingStatus = ProductingStatus.已下发;
                            planTemp.DispatcherId = GetCurrentUser().Id;
                            planTemp.DispatcherName = GetCurrentUser().Surname + GetCurrentUser().Name;
                            var jobNumber = _codeFormatDescAppServiceRepsitory.GetCodeFormat("生产计划");
                            if (jobNumber == null)
                            {
                                planTemp.JobNumber = _codeFormatDescAppServiceRepsitory.GetOrderCode("SCJH", "yyyyMMdd", 1, 5, 1);
                            }
                            else
                            {
                                planTemp.JobNumber = jobNumber;
                            }
                            //planTemp.JobNumber = _codeFormatDescAppServiceRepsitory.GetOrderCode("PDA", "yyyyMMdd", 1, 5, 1);//调用正茂接口生成编号
                            planTemp.IssueTime = DateTime.Now;
                            planTemp.Issue = true;
                            _productionSchedulerRepository.Update(planTemp);
                            _iOperationHistoryAppService.InsertOperationLogNew(planTemp.Id, BusinessTypes.生产计划, OperationTypes.修改生产计划, "修改" + planTemp.ProductionName + "的生产计划");

                        }
                        else
                        {
                            resultMessage.code = 1;
                            resultMessage.Message = "传入数据有误!";
                            return resultMessage;
                            //throw new Exception("传入数据有误!");
                        }
                    }
                    //var tempParentId = planList.First().ParentId;
                    //var planSibling = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == tempParentId && !guidList.Contains(d.Id));
                    //bool siblingFlag = false;
                    //if (planSibling.Count() > 0)
                    //{  
                    //    foreach (var item in planSibling)
                    //    {
                    //        if (item.ProductingStatus != ProductingStatus.已下发)
                    //        {
                    //            siblingFlag = true;
                    //            break;
                    //        }
                    //    }
                    //}
                    //if (!siblingFlag)
                    //{
                    //    var temp = _productionSchedulerRepository.GetAll().Where(d => d.NodeId== tempParentId).FirstOrDefault();
                    //    if (temp != null)
                    //    {
                    //        temp.IsCascade=true;
                    //        temp.ProductingStatus = ProductingStatus.已下发;
                    //        temp.IssueTime = DateTime.Now;
                    //        _productionSchedulerRepository.Update(temp);
                    //    }
                    //}
                    resultMessage.code = 0;
                    return resultMessage;
                }
                else
                {
                    resultMessage.code = 1;
                    resultMessage.Message = "下发任务失败！";
                    return resultMessage;
                }
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }
        /// <summary>
        /// 同步修改单个计划
        /// </summary>
        /// <param name="input"></param>
        public ResultMessage UpatePlan(HandManageInput input)
        {
            ResultMessage resultMessage = new ResultMessage();
            try
            {
                if (input.GuidList == null)
                {
                    resultMessage.code = 0;
                    return resultMessage;
                }
                Dictionary<Guid, decimal> mapHour = new Dictionary<Guid, decimal>();
                List<ProductionScheduler> schedulers = new List<ProductionScheduler>();
                List<CriticalPath> criticals = new List<CriticalPath>();
                CriticalPath critical = new CriticalPath();
                critical.Way = "";
                critical.ComputeHour = 0;

                if (input.GuidList.Count == 1)
                {
                    var planTemp = _productionSchedulerRepository.GetAll().Where(d => d.Id == input.GuidList.First()).FirstOrDefault();
                    if (planTemp != null)
                    {
                        var planBrother = _productionSchedulerRepository.GetAll().Where(d => d.ParentId == planTemp.ParentId && d.Id != planTemp.Id);
                        foreach (var item in planBrother)
                        {
                            item.Color = "black";
                            _productionSchedulerRepository.Update(item);
                        }
                        planTemp.StartTime = input.StartTime.Value;
                        planTemp.EndTime = input.EndTime.Value;
                        planTemp.UserId = input.UserId;
                        planTemp.UserName = input.UserName;

                        planTemp.OrganizationUnitId = input.OrganizationUnitId;
                        planTemp.OrganizationUnitDesc = input.OrganizationUnitDesc;

                        //if (!string.IsNullOrEmpty(input.UserId))
                        //{
                        //    if (input.UserId.Contains(","))
                        //    {
                        //        var userArray = input.UserId.Split(',').ToList().Select<string, long>(x => Convert.ToInt64(x));
                        //        var query = from temp in UserManager.Users.Where(d => userArray.Contains(d.Id))
                        //                    join ou in _userOrganizationUnitRepository.GetAll() on temp.Id equals ou.UserId
                        //                    join cp in _organizationUnitRepository.GetAll() on ou.OrganizationUnitId equals cp.Id
                        //                    select new
                        //                    {
                        //                        Id = temp.Id,
                        //                        DisplayName = cp.DisplayName
                        //                    };

                        //        planTemp.OrganizationUnitId = string.Join(",", query.Select(d => d.Id));
                        //        planTemp.OrganizationUnitDesc = string.Join(",", query.Select(d => d.DisplayName));
                        //    }
                        //    else
                        //    {
                        //        long userId;
                        //        bool result = long.TryParse(input.UserId, out userId);
                        //        if (result)
                        //        {
                        //            var query = from temp in UserManager.Users.Where(d => d.Id == userId)
                        //                        join ou in _userOrganizationUnitRepository.GetAll() on temp.Id equals ou.UserId
                        //                        join cp in _organizationUnitRepository.GetAll() on ou.OrganizationUnitId equals cp.Id
                        //                        select new
                        //                        {
                        //                            Id = temp.Id,
                        //                            DisplayName = cp.DisplayName
                        //                        };
                        //            planTemp.OrganizationUnitId = string.Join(",", query.Select(d => d.Id));
                        //            planTemp.OrganizationUnitDesc = string.Join(",", query.Select(d => d.DisplayName));
                        //        }
                        //    }
                        //}
                        //planTemp.DispatcherId = input.DispatcherId;
                        //planTemp.DispatcherName = input.DispatcherName;
                        planTemp.Remark = input.Remark;
                        planTemp.ArrangementTime = DateTime.Now;
                        planTemp.PerformanceHour = input.PerformanceHour;
                        planTemp.Color = "red";
                        _productionSchedulerRepository.Update(planTemp);
                        _iOperationHistoryAppService.InsertOperationLog(planTemp.Id, 8, 15, "修改" + planTemp.ProductionName + "信息");
                        if (input.RenovateFlag)
                        {
                            var lineList = _processLineRepository.GetAll().Where(d => d.PPtr == planTemp.ParentId).ToList();
                            PlainSequence(lineList, planTemp.NodeId, planTemp.ParentId, null, input.EndTime.Value);
                            _iOperationHistoryAppService.InsertOperationLog(planTemp.Id, 8, 15, "同步更新" + planTemp.ProductionName + "的后续路线计划");
                        }
                    }
                    else
                    {
                        resultMessage.code = 1;
                        resultMessage.Message = "传入数据有误!";
                        return resultMessage;
                        //throw new Exception("传入数据有误!");
                    }
                }
                resultMessage.code = 0;
                return resultMessage;
            }
            catch (Exception ex)
            {
                resultMessage.code = 1;
                resultMessage.Message = ex.Message;
                return resultMessage;
            }
        }

        /// <summary>
        /// 获取调度员
        /// </summary>
        /// <returns></returns>
        public List<UserListDto> GetDispatcherList()
        {
            var userList = (from cc in _userRepository.GetAll()
                            select new UserListDto
                            {
                                Id = cc.Id,
                                Name = cc.Surname + cc.Name,
                                Surname = cc.Surname,
                                UserName = cc.Surname+cc.Name,
                                EmailAddress = cc.EmailAddress,
                                PhoneNumber = cc.PhoneNumber,
                                ProfilePictureId = cc.ProfilePictureId,
                                IsEmailConfirmed = cc.IsEmailConfirmed,
                                IsActive = cc.IsActive,
                                CreationTime = cc.CreationTime
                            }).ToList();
         
            return userList;
        }

        /// <summary>
        /// 根据Id获取单个计划
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public ProductionSchedulerOutput GetSchedulerById(Guid Id)
        {
            var tempSche = _productionSchedulerRepository.FirstOrDefault(d => d.Id == Id);
            if (tempSche != null)
            {
                var result = ObjectMapper.Map<ProductionSchedulerOutput>(tempSche);
                return result;
            }
            else
            {

                throw new UserFriendlyException("系统未查找到该信息！请重新查询！");
            }

        }

        #region 核心算法

        /// <summary>
        /// 顺序修改计划，不修改父节点
        /// </summary>
        /// <param name="processLines"></param>
        /// <param name="guid"></param>
        /// <param name="ParentId"></param>
        /// <param name="specialDate"></param>
        /// <param name="endTime"></param>
        private void PlainSequence(List<ProcessLine> processLines, Guid guid, Guid ParentId, List<DateTime> specialDate, DateTime endTime)
        {
            DateTime endTimeTemp = new DateTime(endTime.Ticks);
            var temp = processLines.Where(d => d.From == guid).FirstOrDefault();
            if (temp != null)
            {
                var scheduler = _productionSchedulerRepository.GetAll().Where(d => d.NodeId == temp.To).FirstOrDefault();
                if (temp.To != ParentId && scheduler != null)
                {
                    DateTime planTime = AssignWorkHour(endTime, scheduler.WorkingHour, specialDate, 0);
                    scheduler.StartTime = planTime;
                    scheduler.EndTime = endTime;
                    scheduler.Color = "red";
                    _productionSchedulerRepository.Update(scheduler);
                    endTimeTemp = planTime;
                }
                PlainSequence(processLines, temp.To, ParentId, specialDate, endTimeTemp);
            }
        }
         
        /// <summary>
        /// 查找关键路径
        /// </summary>
        /// <param name="processLines"></param>
        /// <param name="map"></param>
        /// <param name="form">当前节点ID</param>
        /// <param name="result"></param>
        /// <param name="critical"></param>
        /// <param name="productionSchedulers"></param>
        /// <param name="endTime"></param>
        /// <param name="specialDate"></param>
        private void CriticalRecursion(List<ProcessLine> processLines, Dictionary<Guid, decimal> map, Guid form, List<CriticalPath> result, CriticalPath critical, List<ProductionScheduler> productionSchedulers, DateTime endTime, List<DateTime> specialDate, int Flag = 0)
        {
            //当前时间{2022/5/25 10:18:06}
            DateTime endTimeTemp = new DateTime(endTime.Ticks);
            CriticalPath criticalTemp = new CriticalPath();
            criticalTemp.Way = critical.Way;
            criticalTemp.ComputeHour = critical.ComputeHour;
            //查看工艺路线有几条分支
            var temp = processLines.Where(d => d.To == form).ToList();
            if (temp.Count == 0)
            {
                result.Add(criticalTemp);
            }
            for (int i = 0; i < temp.Count; i++)
            {
                //如果不包含
                if (!criticalTemp.Way.Contains(temp[i].From.ToString()))
                {
                    //路径长度
                    criticalTemp.Way = criticalTemp.Way + "," + temp[i].From;
                    //用node节点信息 和路线信息相匹配 条件nodeid
                    if (map.ContainsKey(temp[i].From))
                    {
                        //路径工时
                        criticalTemp.ComputeHour = criticalTemp.ComputeHour + map[temp[i].From];
                        if (Flag == 0)
                        {
                            DateTime planTime = AssignWorkHour(endTime, map[temp[i].From], specialDate, 1);
                            if (productionSchedulers != null)
                            {
                                //维护计划
                                if (productionSchedulers.Count > 0)
                                {
                                    var scheduler = productionSchedulers.Where(d => d.NodeId == temp[i].From).First();
                                    scheduler.StartTime = planTime;
                                    scheduler.EndTime = endTime;
                                    endTimeTemp = planTime;
                                }
                            }
                            else
                            {
                                throw new UserFriendlyException("计划任务不可为空!");

                            }

                        }
                    }
                    CriticalRecursion(processLines, map, temp[i].From, result, criticalTemp, productionSchedulers, endTimeTemp, specialDate);
                }
              
            }
        }

        /// <summary>
        /// 查找当前节点类型 1 任务-节点  2 节点-节点 3 节点-工序 4 工序-工步 5 工步
        /// </summary>
        /// <param name="ParentId"></param>
        /// <returns></returns>
        private int RouteType(Guid ParentId)
        {
            var bopDesc = _bopDescRepository.GetAll().Where(d => d.Id == ParentId).FirstOrDefault();
            if (bopDesc != null)
            {
                return 1;
            }
            var bopNode = _bopNodeRepository.GetAll().Where(d => d.Id == ParentId).FirstOrDefault();
            if (bopNode != null)
            {
                if (!string.IsNullOrEmpty(bopNode.ProcessCode))
                {
                    return 3;
                }
                else
                {
                    return 2;
                }
            }
            var processEntity = _processesEntityRepository.GetAll().Where(d => d.Id == ParentId).FirstOrDefault();
            if (processEntity != null)
            {
                return 4;
            }
            var workEntity = _workStepEntityRepository.GetAll().Where(d => d.Id == ParentId).FirstOrDefault();
            if (workEntity != null)
            {
                return 5;
            }
            return 0;
        }
        /// <summary>
        /// 计算工时，排除工作日,特殊日期。
        /// </summary>
        /// <param name="plannedWork">计划日期</param>
        /// <param name="taskTime">工时</param>
        /// <param name="specialDate">特殊日期</param>
        /// <param name="treatmentStyle">0加 1减</param>
        /// <returns></returns>
        private DateTime AssignWorkHour(DateTime plannedWork, decimal taskTime, List<DateTime> specialDate, int treatmentStyle)
        {
            //0 加 的意思就是 根据plannedWork 先计算每天 配置 上午 干的工时 下午干的工时 排除 周六 周天  特殊如期 然后 加想要加的工期就可以 
            //1 减 的意思就是 根据plannedWork 先计算每天 配置 上午 干的工时 下午干的工时 排除 周六 周天  特殊如期 然后 倒退

            List<string> specialList = new List<string>();

            if (specialDate != null)
            {
                foreach (var item in specialDate)
                {
                    specialList.Add(item.ToShortDateString().ToString());
                }
            }
            //先算整天排除 周六周天 特殊日期
            if (treatmentStyle == 0)
            {
                string tempStr = plannedWork.ToShortDateString().ToString();
                if (plannedWork.DayOfWeek == System.DayOfWeek.Saturday || plannedWork.DayOfWeek == System.DayOfWeek.Sunday || specialList.Contains(tempStr))
                {
                    for (int i = 0; i < 7; i++)
                    {
                        var tempDate = plannedWork.AddDays(1);
                        tempStr = tempDate.ToShortDateString().ToString();
                        if (tempDate.DayOfWeek != System.DayOfWeek.Saturday && tempDate.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(tempStr))
                        {
                            plannedWork = Convert.ToDateTime(tempStr + " " + forenoonStart);
                            break;
                        }
                    }
                }
            }
            else
            {
                string tempStr = plannedWork.ToShortDateString().ToString();
                if (plannedWork.DayOfWeek == System.DayOfWeek.Saturday || plannedWork.DayOfWeek == System.DayOfWeek.Sunday || specialList.Contains(tempStr))
                {
                    for (int i = 0; i < 7; i++)
                    {
                        var tempDate = plannedWork.AddDays(-1);
                        tempStr = tempDate.ToShortDateString().ToString();
                        if (tempDate.DayOfWeek != System.DayOfWeek.Saturday && tempDate.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(tempStr))
                        {
                            plannedWork = Convert.ToDateTime(tempStr + " " + afternoonEnd);
                           
                            break;
                        }
                    }
                }
            }


            decimal tempDay = taskTime / (decimal)8.0;
            int taskDay = (int)tempDay; //需要新增的天数
            decimal tempHour = taskTime - taskDay * (decimal)8.0;//需要新增的小时数
                                                                 //默认一天8小时 8:30-11:30  13:30-18:30 上午3下午5

           
          

            for (int i = 0; i < taskDay; i++)
            {
                int itemp = 0;
                if (treatmentStyle == 0)
                {
                    itemp = 1;

                }
                else
                {
                    itemp = -1;
                }
                DateTime tempDt = plannedWork.AddDays(itemp);
                string tempStr = tempDt.ToShortDateString().ToString();
                if (tempDt.DayOfWeek != System.DayOfWeek.Saturday && tempDt.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(tempStr))
                {
                    plannedWork = tempDt;

                }
                else 
                {
                    if (treatmentStyle == 0)
                    {
                        for (int j = 1; j < 8; j++)
                        {
                            DateTime tempDtPlan = plannedWork.AddDays(1*j);
                            tempStr = tempDtPlan.ToShortDateString().ToString();
                            if (tempDtPlan.DayOfWeek != System.DayOfWeek.Saturday && tempDtPlan.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(tempStr))
                            {
                                plannedWork = tempDtPlan;
                                break;
                            }
                        }

                    }
                    else
                    {
                        for (int j = 1; j < 8; j++)
                        {
                            DateTime tempDtPlan = plannedWork.AddDays(-1*j);
                            tempStr = tempDtPlan.ToShortDateString().ToString();
                            if (tempDtPlan.DayOfWeek != System.DayOfWeek.Saturday && tempDtPlan.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(tempStr))
                            {
                                plannedWork = tempDtPlan;
                                break;
                            }
                        }
                    }

                }
            }
            string plannedTemp = plannedWork.ToShortDateString().ToString();
            DateTime forenoonStartTime = Convert.ToDateTime(plannedTemp + " " + forenoonStart);
            DateTime forenoonEndTime = Convert.ToDateTime(plannedTemp + " " + forenoonEnd);
            DateTime afternoonStartTime = Convert.ToDateTime(plannedTemp + " " + afternoonStart);
            DateTime afternoonEndTime = Convert.ToDateTime(plannedTemp + " " + afternoonEnd);
            var forenoonDiff = Convert.ToInt32(forenoonEnd.Split(':')[0]) - Convert.ToInt32(forenoonStart.Split(':')[0]);
            var afternoonDiff = Convert.ToInt32(afternoonEnd.Split(':')[0]) - Convert.ToInt32(afternoonStart.Split(':')[0]);
            //不在时间段的特殊处理
            if (DateTime.Compare(forenoonStartTime, plannedWork) > 0)
            {
                plannedWork = forenoonStartTime;
            }
            else if (DateTime.Compare(forenoonEndTime, plannedWork) <= 0 && DateTime.Compare(afternoonStartTime, plannedWork) > 0)
            {
                plannedWork = afternoonStartTime;
            }
            else if (DateTime.Compare(plannedWork, afternoonEndTime) > 0)
            {
                plannedWork = afternoonEndTime;
            }
            bool nodeFlag = true;

            //计算当前计划的时候是上午 还是下午 上午的话 截止到 上午规定的开始节点 在倒退就 到前一天的结束时间  其他的 也同理

            if (DateTime.Compare(forenoonStartTime, plannedWork) <= 0 && DateTime.Compare(forenoonEndTime, plannedWork) >= 0)
            {

                if (treatmentStyle == 0)
                {
                    TimeSpan hoursSpan = new TimeSpan(forenoonEndTime.Ticks - plannedWork.Ticks);
                    var temp = (decimal)hoursSpan.TotalHours;//计算差距多少小时
                    if (tempHour > temp)
                    {
                        var goBeyond = tempHour - temp; //超出多少小时 从下午计算
                        if (goBeyond <= afternoonDiff)
                        {
                            plannedWork = afternoonStartTime.AddHours((double)goBeyond);
                        }
                        else
                        {
                            goBeyond = tempHour - afternoonDiff;
                            var overDay = Convert.ToDateTime(plannedWork.AddDays(1).ToShortDateString().ToString() + " " + forenoonStart);
                            while (nodeFlag)
                            {
                                if (overDay.DayOfWeek != System.DayOfWeek.Saturday && overDay.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(overDay.ToShortDateString()))
                                {
                                    nodeFlag = false;
                                }
                                else
                                {
                                    overDay = overDay.AddDays(1);
                                }
                            }
                            plannedWork = overDay.AddHours((double)goBeyond);
                        }
                    }
                    else
                    {
                        plannedWork = plannedWork.AddHours((double)tempHour);
                    }
                }
                else
                {
                    TimeSpan hoursSpan = new TimeSpan(plannedWork.Ticks - forenoonStartTime.Ticks);
                    var temp = (decimal)hoursSpan.TotalHours;//计算差距多少小时
                    if (tempHour > temp)
                    {
                        var goBeyond = tempHour - temp; //超出多少小时 从第二天计算

                        if (goBeyond <= afternoonDiff)
                        {
                            var preDay = Convert.ToDateTime(plannedWork.AddDays(-1).ToShortDateString().ToString() + " " + afternoonEnd);
                            while (nodeFlag)
                            {
                                if (preDay.DayOfWeek != System.DayOfWeek.Saturday && preDay.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(preDay.ToShortDateString()))
                                {
                                    nodeFlag = false;
                                }
                                else
                                {
                                    preDay = preDay.AddDays(-1);
                                }
                            }
                            plannedWork = preDay.AddHours((double)goBeyond * -1);
                        }
                        else
                        {
                            var preDay = Convert.ToDateTime(plannedWork.AddDays(-1).ToShortDateString().ToString() + " " + forenoonEnd);
                            while (nodeFlag)
                            {
                                if (preDay.DayOfWeek != System.DayOfWeek.Saturday && preDay.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(preDay.ToShortDateString()))
                                {
                                    nodeFlag = false;
                                }
                                else
                                {
                                    preDay = preDay.AddDays(-1);
                                }
                            }
                            goBeyond = goBeyond - afternoonDiff;
                            plannedWork = preDay.AddHours((double)goBeyond * (-1));
                        }
                    }
                    else
                    {
                        plannedWork = plannedWork.AddHours((double)tempHour * (-1));
                    }
                }


            }
            if (DateTime.Compare(afternoonStartTime, plannedWork) <= 0 && DateTime.Compare(afternoonEndTime, plannedWork) >= 0)
            {
                if (treatmentStyle == 0)
                {
                    TimeSpan hoursSpan = new TimeSpan(afternoonEndTime.Ticks - plannedWork.Ticks);
                    var temp = (decimal)hoursSpan.TotalHours;//计算差距多少小时
                    if (tempHour > temp)
                    {

                        var goBeyond = tempHour - temp; //超出多少小时 从下午计算
                        if (goBeyond <= forenoonDiff)
                        {
                            var overDay = Convert.ToDateTime(plannedWork.AddDays(1).ToShortDateString().ToString() + " " + forenoonStart);
                            while (nodeFlag)
                            {
                                if (overDay.DayOfWeek != System.DayOfWeek.Saturday && overDay.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(overDay.ToShortDateString()))
                                {
                                    nodeFlag = false;
                                }
                                else
                                {
                                    overDay = overDay.AddDays(1);
                                }
                            }
                            plannedWork = overDay.AddHours((double)goBeyond);
                        }
                        else
                        {
                            var overDay = Convert.ToDateTime(plannedWork.AddDays(1).ToShortDateString().ToString() + " " + afternoonStart);
                            while (nodeFlag)
                            {
                                if (overDay.DayOfWeek != System.DayOfWeek.Saturday && overDay.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(overDay.ToShortDateString()))
                                {
                                    nodeFlag = false;
                                }
                                else
                                {
                                    overDay = overDay.AddDays(1);
                                }
                            }
                            goBeyond = goBeyond - forenoonDiff;
                            plannedWork = overDay.AddHours((double)goBeyond);
                        }
                    }
                    else
                    {
                        plannedWork = plannedWork.AddHours((double)tempHour);
                    }
                }
                else
                {
                    TimeSpan hoursSpan = new TimeSpan(plannedWork.Ticks - afternoonStartTime.Ticks);
                    var temp = (decimal)hoursSpan.TotalHours;//计算差距多少小时
                    if (tempHour > temp)
                    {

                        var goBeyond = tempHour - temp; //超出多少小时
                        if (goBeyond <= forenoonDiff)
                        {
                            plannedWork = forenoonEndTime.AddHours((double)goBeyond * (-1));
                        }
                        else
                        {
                            var overDay = Convert.ToDateTime(plannedWork.AddDays(-1).ToShortDateString().ToString() + " " + afternoonEnd);
                            while (nodeFlag)
                            {
                                if (overDay.DayOfWeek != System.DayOfWeek.Saturday && overDay.DayOfWeek != System.DayOfWeek.Sunday && !specialList.Contains(overDay.ToShortDateString()))
                                {
                                    nodeFlag = false;
                                }
                                else
                                {
                                    overDay = overDay.AddDays(-1);
                                }
                            }
                            goBeyond = goBeyond - forenoonDiff;
                            plannedWork = overDay.AddHours((double)goBeyond * (-1));
                        }
                    }
                    else
                    {
                       plannedWork = plannedWork.AddHours((double)tempHour * (-1));
                        
                       
                    }
                }

            }
            return plannedWork;
        }

        private class CriticalPath
        {
            public string Way { get; set; }

            public decimal ComputeHour { get; set; }
        }


        /// <summary>
        /// 根据枚举获取枚举描述信息
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        private static string GetEnumDesc(System.Enum parm)
        {
            FieldInfo enumInfo = parm.GetType().GetField(parm.ToString());
            if (enumInfo == null)
            {
                return "";
            }
            DescriptionAttribute[] enumAttributes
                = (DescriptionAttribute[])enumInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (enumAttributes.Length > 0)
            {
                return enumAttributes[0].Description;
            }
            return parm.ToString();
        }
        /// <summary>
        /// 获取配套状态
        /// </summary>
        /// <param name="processDosage">工艺用量</param>
        /// <param name="suiteStock">配套数量</param>
        /// <param name="preSuiteStock">预配套数量</param>
        /// <returns></returns>
        private string GetAssortStateDesc(int processDosage, int suiteStock, int preSuiteStock, int available)
        {

            if (preSuiteStock == 0)
            {
                return "未预配套";
            }
            // 缺料：
            if (processDosage - suiteStock > available)
            {
                return "缺料";
            }
            else
            {
                if (processDosage - suiteStock == 0)
                {
                    return "已配套";
                }
                if (suiteStock == 0)
                {
                    return "未配套";
                }
                return "配套中";
            }
        }
        #endregion





        /// <summary>
        /// 根据节点获取当前的工艺规程
        /// </summary>
        /// <param name="id"></param>
        /// <param name="techniqueName"></param>
        /// <param name="techniqueNumber"></param>
        /// <param name="isExport"></param>
        /// <returns></returns>
        public List<TechSelctResult> GetTechListByNodeId(Guid id, string techniqueName, string techniqueNumber,bool? isExport)
        {
             List<TechSelctResult> teches = new List<TechSelctResult>();
            if (id != Guid.Empty)
            {
                int route = RouteType(id);
                if (route == 1)
                {
                    var techIds = _bopNodeRepository.GetAll().Where(d => d.BopDescId == id).Where(d => d.TechniqueEntityId != null).Select(d => d.TechniqueEntityId).ToList();
                    if (techIds.Count() > 0)
                    {
                        //var modifRes = _modifyManageRepository.GetAll().Where(d => d.DocumentStatus == DocumentStatus.审核中).Select(d => d.TechniqueId).ToList();
                        //if (modifRes.Count() > 0)
                        //{
                        //    for (int i = 0; i < techIds.Count; i++)
                        //    {
                        //        if (modifRes.FindIndex(d => d == techIds[i]) != -1)
                        //        {
                        //            techIds.Remove(techIds[i]);
                        //        }
                        //    }
                        //}
                        teches = (  from cc in _techniqueEntityRepository.GetAll()
                                    join ee in _bopNodeRepository.GetAll() on cc.Id equals ee.TechniqueEntityId
                                    join mm in techIds on cc.Id equals mm
                                    select new TechSelctResult
                                    {
                                        Id = cc.Id,
                                        TechniqueName = cc.TechniqueName,
                                        TechniqueNumber = cc.TechniqueNumber,
                                        Edition=cc.Edition,
                                        FileStatusDesc= GetEnumDesc(cc.FileStatus),
                                        BopExprot=ee.BopExprot,
                                        PlanExprot=ee.PlanExprot,
                                    }).ToList();
                    }
                }
                if (route == 2)
                {
                    var bopNode = _bopNodeRepository.Get(id);
                    var techIds = _bopNodeRepository.GetAll().Where(d => d.NodeCode.StartsWith(bopNode.NodeCode) && d.BopDescId == bopNode.BopDescId).Where(d => d.TechniqueEntityId != null).Select(d => d.TechniqueEntityId).ToList();
                    if (techIds.Count() > 0)
                    {
                        //var modifRes = _modifyManageRepository.GetAll().Where(d => d.DocumentStatus == DocumentStatus.审核中).Select(d => d.TechniqueId).ToList();
                        //if (modifRes.Count() > 0)
                        //{
                        //    for (int i = 0; i < techIds.Count; i++)
                        //    {
                        //        if (modifRes.FindIndex(d => d == techIds[i]) != -1)
                        //        {
                        //            techIds.Remove(techIds[i]);
                        //        }
                        //    }
                        //}
                        teches = (from cc in _techniqueEntityRepository.GetAll()
                                  join ee in _bopNodeRepository.GetAll() on cc.Id equals ee.TechniqueEntityId
                                  join mm in techIds on cc.Id equals mm
                                  select new TechSelctResult
                                  {
                                      Id = cc.Id,
                                      TechniqueName = cc.TechniqueName,
                                      TechniqueNumber = cc.TechniqueNumber,
                                      Edition = cc.Edition,
                                      FileStatusDesc = GetEnumDesc(cc.FileStatus),
                                      BopExprot = ee.BopExprot,
                                      PlanExprot = ee.PlanExprot,
                                  }).ToList();
                    }
                }
                if (route == 3)
                {
                    var bopNode = _bopNodeRepository.Get(id);
                    var tech = _techniqueEntityRepository.GetAll().Where(d=>d.Id==bopNode.TechniqueEntityId.Value).FirstOrDefault();
                    var modifRes = _modifyManageRepository.GetAll().Where(d => d.DocumentStatus == DocumentStatus.审核中).Select(d => d.TechniqueId).ToList();
                    if (tech != null)
                    {
                        //if (modifRes.Count > 0)
                        //{
                        //    if (modifRes.FindIndex(d => d == tech.Id) == -1)
                        //    {
                        //        TechSelctResult temp = new TechSelctResult();
                        //        temp.Id = tech.Id;
                        //        temp.TechniqueName = tech.TechniqueName;
                        //        temp.TechniqueNumber = tech.TechniqueNumber;
                        //        teches.Add(temp);
                        //    }
                        //}
                        //else
                        //{
                        TechSelctResult temp = new TechSelctResult();
                        temp.Id = tech.Id;
                        temp.TechniqueName = tech.TechniqueName;
                        temp.TechniqueNumber = tech.TechniqueNumber;
                        temp.Edition = tech.Edition;
                        temp.FileStatusDesc = GetEnumDesc(tech.FileStatus);
                        temp.BopExprot = bopNode.BopExprot;
                        temp.PlanExprot = bopNode.PlanExprot;
                        teches.Add(temp);
                        //}
                    }
                }
            }
            if (isExport == null)
            {
                return teches.AsQueryable().WhereIf(!string.IsNullOrEmpty(techniqueName), d => d.TechniqueName.Contains(techniqueName)).WhereIf(!string.IsNullOrEmpty(techniqueNumber), d => d.TechniqueNumber.Contains(techniqueNumber)).OrderBy(d => d.BopExprot).ToList();
            }
            else
            {
                return teches.AsQueryable().WhereIf(!string.IsNullOrEmpty(techniqueName), d => d.TechniqueName.Contains(techniqueName)).WhereIf(!string.IsNullOrEmpty(techniqueNumber), d => d.TechniqueNumber.Contains(techniqueNumber)).Where(d=>d.BopExprot==isExport).ToList();
            }
        
        }

        public bool GetShowBanZuFlag(List<Guid> guids,Guid bopDescId)
        {
            if (guids.Count > 0)
            {
                var tempData = from cc in _bopNodeRepository.GetAll().Where(d => d.BopDescId == bopDescId && d.TechniqueEntityId != null)
                               join mm in guids on cc.Id equals mm
                               select cc;
                if (tempData.Count() > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
    } 
}
